package configs

import (
	_ "embed"
	"encoding/base64"
	"github.com/dgrijalva/jwt-go"
	"github.com/go-playground/validator/v10"
	"github.com/pelletier/go-toml"
	"os"
	"time"
)

type FileConfig struct {
	IsProd          bool
	ApiTimeout      time.Duration
	FrontendAddress string
	RequiredVersion int

	DB struct {
		Driver  string `validate:"required"`
		Source  string `validate:"required"`
		MaxIdle int
		MaxOpen int
	}

	Auth struct {
		LoginExpire  time.Duration
		AccessExpire time.Duration
	}

	Listen struct {
		Http        string
		Https       string
		Smtp        string
		Smtps       string
		Imap        string
		Imaps       string
		MtaStsHttp  string
		MtaStsHttps string

		Rpc string
	}

	Path struct {
		Log string `validate:"required"`
	}

	SecKey struct {
		Login  string `validate:"required"`
		Object string `validate:"required"`
	}

	Setting struct {
		TxTimeout time.Duration
	}

	SmtpService struct {
		AuthToken string `validate:"required"`
		Username  string `validate:"required"`
	}

	InfluxDB struct {
		ServerURL string
		AuthToken string
		Org       string
		Bucket    string
	}

	TLS struct {
		// open tls gRPC service
		SafeConnection bool
		// location of server.pem
		CertFile string
		// location of server.key
		KeyFile string
		// location of ca.pem
		CaFile string
	}

	RabbitMQ struct {
		URL string
	}
}

var Config = FileConfig{}

//go:embed default.toml
var defaultConfig []byte

func LoadToml(tomlFile string) error {
	if err := toml.Unmarshal(defaultConfig, &Config); err != nil {
		return err
	}

	f, err := os.ReadFile(tomlFile)
	if err != nil {
		return err
	}
	if err := toml.Unmarshal(f, &Config); err != nil {
		return err
	}

	if err := validator.New().Struct(Config); err != nil {
		return err
	}

	// encoding Secure Key
	{
		LoginSecKey, err = base64.StdEncoding.DecodeString(Config.SecKey.Login)
		if err != nil {
			return err
		}
		ObjectSecKey, err = base64.StdEncoding.DecodeString(Config.SecKey.Object)
		if err != nil {
			return err
		}
	}

	return nil
}

var LoginSecKey []byte
var ObjectSecKey []byte

func JwtSecureKey(_ *jwt.Token) (interface{}, error) {
	return LoginSecKey, nil
}

func JwtObjectKey(_ *jwt.Token) (interface{}, error) {
	return ObjectSecKey, nil
}
